package com.rockcent.mall.controller;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.rockcent.common.common.JsonResult;
import com.rockcent.common.common.PageResult;
import com.rockcent.common.common.RestDoing;
import com.rockcent.common.controller.BaseController;
import com.rockcent.common.domain.enumclass.Whether;
import com.rockcent.common.utils.RDateUtils;
import com.rockcent.common.utils.RequestUtils;
import com.rockcent.helper.SysMessageHelper;
import com.rockcent.mall.Prop;
import com.rockcent.mall.Routes;
import com.rockcent.mall.lib.constants.SysMessageConstants;
import com.rockcent.mall.lib.domain.*;
import com.rockcent.mall.lib.domain.enumclass.*;
import com.rockcent.mall.lib.dto.MerchantCouponDto;
import com.rockcent.mall.lib.dto.QrCodeDto;
import com.rockcent.mall.lib.dto.UploadImageFileDto;
import com.rockcent.mall.lib.dto.UserInfoDto;
import com.rockcent.mall.lib.helper.BaseUserHelper;
import com.rockcent.mall.lib.helper.QRCodeHelper;
import com.rockcent.mall.lib.repository.*;
import org.apache.commons.lang3.EnumUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.sql.Date;
import java.util.Iterator;
import java.util.List;

/**
 * 卡券管理
 * Created by zhangjh on 2016/10/11.
 *
 */
@RestController
public class MerchantCouponController extends BaseController {

    private final Logger log = LoggerFactory.getLogger(MerchantCouponController.class);

    @Autowired
    private BaseUserHelper userHelper;

    @Autowired
    private ObjectMapper objectMapper;

    @Autowired
    private QRCodeHelper qrCodeHelper;

    @Autowired
    private Prop prop;


    @Autowired
    private MerchantCouponRepository merchantCouponRepository;

    @Autowired
    private IntegrationCouponAuditRepository integrationCouponAuditRepository;

    @Autowired
    private MerchantRepository merchantRepository;

    @Autowired
    private CouponMerchantProductsRepository couponMerchantProductsRepository;

    @Autowired
    private CouponMerchantStoreRepository couponMerchantStoreRepository;

    @Autowired
    private MerchantProductRepository merchantProductRepository;
    @Autowired
    private MerchantStoreRepository merchantStoreRepository;

    @Autowired
    private MallRepository mallRepository;

    @Autowired
    private IntegrationEventRepository integrationEventRepository;

    /**
     * @api {get} /merchant/giftPackage/coupon/page B端 产品礼包 卡券列表
     * @apiGroup merchant_coupon
     * @apiVersion 1.0.0
     * @apiHeader  {String} userToken 用户token
     * @apiHeader {String} domain    请求域名
     * @apiParam  {String} sharing <code>必要参数 YES 共享卡券| NO 费共享卡券</code> 是否为共享卡券
     * @apiParam  {String} name 卡券名称/ 编号
     * @apiParam  {String} isDesc <code>可选参数 YES 降序| NO 升序</code> 是否倒序排序
     * @apiParam  {String} type <code>可选参数 VOUCHERS 抵用券| DISCOUNT 折扣券</code> 卡券类型
     * @apiParam  {String} isOnLine <code>可选参数 YES 线上使用卡券| NO 线下使用卡券 | 为空表示所有卡券</code>卡券使用范围
     * @apiParam  {String} orderFieldName <code>可选参数 face_value 面值|leave_total 剩余库存| date_disabled 有效期</code> 用于排序的字段名称
     * @apiParam  {String} status  <code>必须为 状态 WAIT_ISSUE("待发放"), ISSUED("已发放"), SOLDOUT("已下架"), EXPIRED("已过期"), DELETED("已删除"), UNAUDITED("未通过审核"), WAIT_AUDIT("待审核");</code> 状态
     * @apiParam  {Integer} pageNo 页码
     * @apiSuccessExample {json} Success-Response:
     *{
     *"code": "1",
     *"desc": "成功",
     *"data": {
     *  "data": [
     *  {
     *      "id": 1,
     *      "createdAt": "2016-10-08 15:36:20",
     *      "dateCreated": "2016-05-06 17:30:30",
     *      "lastUpdated": "2016-10-19 19:13:57",
     *      "type": "VOUCHERS",
     *      "name": "asd",
     *      "faceValue": 1,
     *      "limitAmount": 12,
     *      "quantity": 12,
     *      "dateEnabled": "2016-08-15 00:00:00.0",
     *      "dateDisabled": "2017-08-15 00:00:00.0",
     *      "useScope": "ALL_STORE",
     *      "dateIssued": "2016-08-15 11:22:00",
     *      "drawLimit": "NO",
     *      "sharing": "NO",
     *      "showOnCenter": "NO",
     *      "showOnMerchant": "NO",
     *      "logoUrl": "http://uploads.rockcent.com/dev/merchant/logo/201610/131336332032d675e6f-482e-4a2f-8e65-40a42f840110Tulips.jpg",
     *      "introduction": "vv阿斯顿",
     *       "status": "VERIFIED",
     *      "merchantId": 1,
     *       "leaveTotal": 12,
     *      "verifiedCount": 0,
     *      "productList": [],
     *      "hadToken": false,
     *      "storeList": []
     *  }
     * ...
     *  ],
     *"totalCount": 3,
     *"totalPage": 1,
     *"pageNo": 0,
     *"pageSize": 10,
     *"nextUrl": /merchant/giftPackage/coupon/page?pageNo=0&pageSize=10
     *"prevUrl":/merchant/giftPackage/coupon/page?pageNo=1&pageSize=10
     *}
     *}
     */
    @RequestMapping(value = Routes.MERCHANT__GIFTPACK_COUPON_PAGE, method = RequestMethod.GET)
    public JsonResult listCoupon(MerchantCouponDto dto, HttpServletRequest request) {
        UserInfoDto userInfoDto = userHelper.getSession(request);
        RestDoing doing = jsonResult -> {
            String sharing = dto.getSharing();
            if (StringUtils.isNotBlank(sharing)) {
                if (!EnumUtils.isValidEnum(Whether.class, sharing)) {
                    jsonResult.remind("sharing 参数错误，必须为 YES(\"是\"), NO(\"否\")", log);
                    return;
                }
            }
            String status = dto.getStatus();
            if (StringUtils.isNotBlank(status)) {
                if (!EnumUtils.isValidEnum(MerchantCouponStatus.class, status)) {
                    jsonResult.remind("getStatus 参数错误,必须为 WAIT_ISSUE(\"待发放\"), ISSUED(\"已发放\"), SOLDOUT(\"已下架\"), EXPIRED(\"已过期\"), DELETED(\"已删除\");",log);
                }
            }
            String isDesc = dto.getIsDesc();
            if (StringUtils.isNotBlank(isDesc)) {
                if (!EnumUtils.isValidEnum(Whether.class, isDesc)) {
                    jsonResult.remind("isDesc 参数错误，必须为 YES(\"是\"), NO(\"否\")", log);
                    return;
                }
            }
            String isOnLine = dto.getIsOnLine();
            if (StringUtils.isNotBlank(isOnLine)) {
                if (!EnumUtils.isValidEnum(Whether.class, isOnLine)) {
                    jsonResult.remind("isOnLine 参数错误，必须为 YES(\"是\"), NO(\"否\")", log);
                    return;
                }
            }
            String couponType = dto.getType();
            if (StringUtils.isNotBlank(couponType)) {
                if (!EnumUtils.isValidEnum(CouponType.class, couponType)) {
                    jsonResult.remind("type 参数错误，必须为  VOUCHERS(\"抵用券\"), DISCOUNT(\"折扣券\")", log);
                    return;
                }
            }
            PageResult page = getPage(dto.getPageNo(), dto.getPageSize());
            Long merchantId = userInfoDto.merchant.getId();
            Long mallId = userInfoDto.mall.getId();
            String dtoName = dto.getName();
            String orderFieldName = dto.getOrderFieldName();
            PageResult<MerchantCouponDto> result = merchantCouponRepository.findByMerchantIdAndSharing(mallId,merchantId, sharing, dtoName, couponType, isOnLine, orderFieldName, isDesc, status, page);
            jsonResult.data = result;
            result.setUrl(Routes.MERCHANT__GIFTPACK_COUPON_PAGE);

        };
        return doing.go(request, log);
    }


    /**
     * @api {get} /merchant/coupon/page B端 卡券列表
     * @apiGroup merchant_coupon
     * @apiVersion 1.0.0
     * @apiHeader  {String} userToken 用户token
     * @apiHeader {String} domain    请求域名
     * @apiParam  {String} name 卡券名称/ 编号
     * @apiParam  {String} type <code>可选参数 VOUCHERS 抵用券| DISCOUNT 折扣券</code> 卡券类型
     * @apiParam  {String} status  <code>必须为 WAIT_ISSUE("待发放"), ISSUED("已发放"), SOLDOUT("已下架"), EXPIRED("已过期"), DELETED("已删除"), WAIT_AUDIT("待审核")</code> 状态
     * @apiParam  {Integer} pageNo 页码
     * @apiSuccessExample {json} Success-Response:
     *{
     *"code": "1",
     *"desc": "成功",
     *"data": {
     *  "data": [
     *      {
     *          "id": 25,
     *          "createdAt": "2016-10-08 15:36:20",
     *          "dateCreated": "2016-06-28 15:08:45",
     *          "lastUpdated": "2016-06-28 15:31:13",
     *          "type": "VOUCHERS",
     *          "name": "expired",
     *          "faceValue": 10,
     *          "limitAmount": 20,
     *          "quantity": 111,
     *          "dateEnabled": "2016-06-26 00:00:00.0",
     *          "dateDisabled": "2016-06-26 00:00:00.0",
     *          "useScope": "ALL_PRODUCT",
     *          "dateIssued": "2016-06-26 15:07:00",
     *          "drawLimit": "NO",
     *          "sharing": "NO",
     *          "showOnCenter": "NO",
     *          "showOnMerchant": "NO",
     *          "logoUrl": "/20160628/20160628150839VdRfDWQ3.png",
     *          "introduction": "dd",
     *          "status": "WAIT_ISSUE",
     *          "merchantId": 1,
     *          "leaveTotal": 111,
     *          "sendTotal": 0,
     *          "verifiedCount": 0,
     *          "productList": [],
     *          "storeList": []
     *     }
     *  ],
     *  "totalCount": 3,
     *  "totalPage": 1,
     *  "pageNo": 0,
     *  "pageSize": 10，
     *  "nextUrl":/merchant/coupon/page?pageNo=0&pageSize=10
     *  "prevUrl":/merchant/coupon/page?pageNo=1&pageSize=10
     *}
     *}
     */
    @RequestMapping(value = Routes.MERCHANT_COUPON_PAGE, method = RequestMethod.GET)
    public JsonResult listCouponPage(MerchantCouponDto dto, HttpServletRequest request) {
        UserInfoDto userInfoDto = userHelper.getSession(request);
        RestDoing doing = jsonResult -> {

            if (StringUtils.isBlank(dto.getStatus()) || !EnumUtils.isValidEnum(MerchantCouponStatus.class, dto.getStatus())) {
                jsonResult.remind("status 参数错误,必须为 WAIT_ISSUE(\"待发放\"), ISSUED(\"已发放\"), SOLDOUT(\"已下架\"), EXPIRED(\"已过期\"), DELETED(\"已删除\"), WAIT_AUDIT(\"待审核\")",log);
                return;
            }

            if (StringUtils.isBlank(dto.getType()) || !EnumUtils.isValidEnum(CouponType.class, dto.getType())) {
                jsonResult.remind("type 参数错误，必须为  ALL(\"全部\"), VOUCHERS(\"抵用券\"), DISCOUNT(\"折扣券\")", log);
                return;
            }

            PageResult page = getPage(dto.getPageNo(), dto.getPageSize());
            PageResult<MerchantCouponDto> result = merchantCouponRepository.findByMerchantId(userInfoDto.merchant.getId(), dto.getName(), dto.getType(), dto.getStatus(), page);
            result.data.forEach(merchantCouponDto -> {
                Long verifiedCount = merchantCouponRepository.countCouponVerified(userInfoDto.merchant.getId(), userInfoDto.mall.getId(), merchantCouponDto.getId(), page);
                merchantCouponDto.setVerifiedCount(verifiedCount==null?0:verifiedCount);
                Long sendTotal = merchantCouponRepository.countCouponSendCustomer(userInfoDto.merchant.getId(), userInfoDto.mall.getId(), merchantCouponDto.getId(), page);
                merchantCouponDto.setSendTotal(sendTotal);
//                String dateEnabled = merchantCouponDto.getDateEnabled();
//                //只需要显示到时分秒，不需要到毫秒
//                if (StringUtils.isNotBlank(dateEnabled)) {
//                    merchantCouponDto.setDateEnabled(dateEnabled.substring(0, dateEnabled.length() - 2));
//                }
//                String dateDisabled = merchantCouponDto.getDateDisabled();
//                //只需要显示到时分秒，不需要到毫秒
//                if (StringUtils.isNotBlank(dateDisabled)) {
//                    merchantCouponDto.setDateDisabled(dateDisabled.substring(0, dateDisabled.length() - 2));
//                }
            });

            result.setUrl(Routes.MERCHANT_COUPON_PAGE);
            jsonResult.data = result;

        };
        return doing.go(request, log);
    }

    /**
     * @api {post} /merchant/coupon/save B端 卡券 保存
     * @apiGroup merchant_coupon
     * @apiVersion 1.0.0
     * @apiHeader  {String}   userToken 用户token
     * @apiHeader  {String}  domain    请求域名
     * @apiParam  {String}   name 卡券名称
     * @apiParam  {String}   type <code>可选参数 VOUCHERS 抵用券| DISCOUNT 折扣券</code> 卡券类型
     * @apiParam  {Double}   discount <code>type 为 DISCOUNT 时，必填</code> 折扣
     * @apiParam  {Double}   faceValue <code>type 为 VOUCHERS 时，必填</code> 面值
     * @apiParam  {Long}    quantity  发放数量
     * @apiParam  {Long}    limitAmount  最低消费金额
     * @apiParam  {String} dateIssued 发放时间
     * @apiParam  {String} dateEnabled  有效期开始时间
     * @apiParam  {String} dateDisabled  有效期结束时间
     * @apiParam {String} isOnLine  <code>YES 线上| NO 线下 </code> 是否线上
     * @apiParam {String} useScope  <code> ALL_STORE 所有门店 | PART_STORE 指定门店 | ALL_PRODUCT 所有产品 | PART_PRODUCT 指定产品 </code> 使用范围
     * @apiParam {String} drawLimit <code> NO 没有上限\")| ALL 总共上限| DAYS 每天上限 </code> 领取限制类型
     * @apiParam {Long} limitCount <code> 默认传1</code>领取限制数
     * @apiParam {String} status  <code>必须为 WAIT_ISSUE("待发放"), ISSUED("已发放"), SOLDOUT("已下架"), EXPIRED("已过期"), DELETED("已删除");</code> 状态
     * @apiParam {String} introduction <code>必填</code> 说明
     * @apiParam {String} logoUrl  <code>必填</code> 图片URL
     * @apiParam {String} sharing: <code>必须为 YES("是"), NO("否")</code>  是否共享卡券
     * @apiParam {String} showOnCenter:<code>必须为 YES("是"), NO("否")</code> 是否发布到领券中心
     * @apiParam {String} showOnMerchant: <code>必须为 YES("是"), NO("否")</code> 是否发布到店铺首页
     * @apiParam {String} integration: <code>必须为 YES("是"), NO("否")</code> 是否发布到积分渠道
     * @apiParam {String} productList: <code>useScope=PART_PRODUCT 时 必传,格式[1,2,3,4]</code> 适用产品ID集合
     * @apiParam {String} storeList: <code>useScope=PART_STORE 时 必传,格式[1,2,3,4]</code> 适用门店ID集合
     *
     * @apiSuccessExample {json} Success-Response:
     *  {
     *   "code": "1",
     *   "desc": "成功"
     *  }
     */
    @Transactional
    @RequestMapping(value = Routes.MERCHANT_COUPON_SAVE, method = RequestMethod.POST)
    public JsonResult saveCoupon(@RequestBody MerchantCouponDto dto, HttpServletRequest request) throws RuntimeException {

        UserInfoDto userInfoDto = userHelper.getSession(request);
        RestDoing doing = jsonResult -> {
            if (StringUtils.isBlank(dto.getType()) || !EnumUtils.isValidEnum(CouponType.class, dto.getType())) {
                jsonResult.remind("type 参数错误，必须为  VOUCHERS(\"抵用券\"), DISCOUNT(\"折扣券\")", log);
                return;
            }

            if (StringUtils.isBlank(dto.getName())) {
                jsonResult.remind("卡券名称不能为空", log);
                return;
            }
            if (StringUtils.isBlank(dto.getStatus()) || !EnumUtils.isValidEnum(MerchantCouponStatus.class, dto.getStatus())) {
                jsonResult.remind("status 参数错误，必须为  WAIT_ISSUE(\"待发放\"), ISSUED(\"已发放\"), SOLDOUT(\"已下架\"), EXPIRED(\"已过期\"), DELETED(\"已删除\");", log);
                return;

            }
            if (StringUtils.isBlank(dto.getSharing()) || !EnumUtils.isValidEnum(Whether.class, dto.getSharing())) {
                jsonResult.remind("sharing 参数错误，必须为  YES(\"是\"), NO(\"否\");", log);
                return;
            }
            if (StringUtils.isBlank(dto.getDrawLimit()) || !EnumUtils.isValidEnum(CouponDrawLimit.class, dto.getDrawLimit())) {
                jsonResult.remind("drawLimit 参数错误，必须为  NO(\"没有上限\"), ALL(\"总共上限\"), DAYS(\"每天上限\");", log);
                return;
            }
            if (dto.getLimitCount() == null) {
                jsonResult.remind("limitCount 不能为空", log);
                return;
            }
            if (StringUtils.isBlank(dto.getLogoUrl())) {
                jsonResult.remind("logoUrl不能为空", log);
                return;
            }

            if (CouponType.DISCOUNT == CouponType.valueOf(dto.getType())) {
                if (dto.getDiscount() == null || "".equals(dto.getDiscount().toString())) {
                    jsonResult.remind("折扣券 折扣不能为空", log);
                    return;
                }
            }
            if (CouponType.VOUCHERS == CouponType.valueOf(dto.getType())) {
                if (dto.getFaceValue() == null || "".equals(dto.getFaceValue().toString())) {
                    jsonResult.remind("抵用券 面值不能为空", log);
                    return;
                }
            }

            if (dto.getLimitAmount() == null || "".equals(dto.getLimitAmount().toString())) {
                jsonResult.remind("卡券最低消费金额不能为空", log);
                return;
            }
            if (dto.getQuantity() == null || "".equals(dto.getQuantity().toString())) {
                jsonResult.remind("卡券发放数量不能为空", log);
                return;
            }
            if (dto.getDateEnabled() == null || "".equals(dto.getDateEnabled().toString())) {
                jsonResult.remind("卡券有效期开始时间不能为空", log);
                return;
            }
            if (dto.getDateDisabled() == null || "".equals(dto.getDateDisabled().toString())) {
                jsonResult.remind("卡券有效期结束时间不能为空", log);
                return;
            }
            if (dto.getIntroduction() == null || "".equals(dto.getIntroduction())) {
                jsonResult.remind("使用说明不能为空", log);
                return;
            }
            if (dto.getDateIssued() == null || "".equals(dto.getDateIssued())) {
                dto.setDateIssued(new Date(System.currentTimeMillis()));
                log.info("======================>马上发放");
            }
            if (StringUtils.isBlank(dto.getUseScope()) || !EnumUtils.isValidEnum(CouponUseScope.class, dto.getUseScope())) {
                jsonResult.remind("useScope 参数错误，必须为   ALL_STORE(\"所有门店\"), PART_STORE(\"指定门店\"),ALL_PRODUCT(\"所有产品\"),\n" +
                        "    PART_PRODUCT(\"指定产品\");", log);
                return;
            }
            if (CouponUseScope.PART_PRODUCT == CouponUseScope.valueOf(dto.getUseScope()) && (dto.getProductList() == null || dto.getProductList().isEmpty())) {
                jsonResult.remind("数据包中未包含产品ID列表",log);
                return;
            }
            if (CouponUseScope.PART_STORE == CouponUseScope.valueOf(dto.getUseScope())) {

                if (dto.getStoreList() == null || dto.getStoreList().isEmpty()) {
                    jsonResult.remind("数据包中未包含门店ID列表",log);
                    return;
                }


            }
            if (StringUtils.isBlank(dto.getSharing()) || !EnumUtils.isValidEnum(Whether.class, dto.getSharing())) {
                jsonResult.remind("sharing 参数错误，必须为 YES(\"是\"), NO(\"否\")", log);
                return;
            }
            if (StringUtils.isBlank(dto.getIsOnLine()) || !EnumUtils.isValidEnum(Whether.class, dto.getIsOnLine())) {
                jsonResult.remind("isOnLine 参数错误，必须为 YES(\"是\"), NO(\"否\")", log);
                return;
            }

            if (StringUtils.isBlank(dto.getShowOnCenter()) || !EnumUtils.isValidEnum(Whether.class, dto.getShowOnCenter())) {
                jsonResult.remind("showOnCenter 参数错误，必须为 YES(\"是\"), NO(\"否\")", log);
                return;
            }


            if (StringUtils.isBlank(dto.getShowOnMerchant()) || !EnumUtils.isValidEnum(Whether.class, dto.getShowOnMerchant())) {
                jsonResult.remind("showOnMerchant 参数错误，必须为 YES(\"是\"), NO(\"否\")", log);
                return;
            }

            MerchantCoupon coupon = new MerchantCoupon();
            coupon.setMerchantName(userInfoDto.merchant.getName());
            //积分兑换条件
            if (null!= dto.getIntegration() && Whether.YES == Whether.valueOf(dto.getIntegration())) {
                dto.setSharing(Whether.NO.toString());
                dto.setShowOnCenter(Whether.NO.toString());
                dto.setShowOnMerchant(Whether.NO.toString());
                dto.setDrawLimit(CouponDrawLimit.INTEGRATION.toString());
                dto.setLimitCount(0L);
                dto.setStatus(MerchantCouponStatus.WAIT_AUDIT.toString());
                //状态待审核
                coupon.setStatus(MerchantCouponStatus.WAIT_AUDIT);

            }
            coupon.setMerchantId(userInfoDto.merchant.getId());
            coupon.setMallId(userInfoDto.mall.getId());
            coupon.setName(dto.getName());
            coupon.setType(CouponType.valueOf(dto.getType()));
            if (CouponType.VOUCHERS == coupon.getType()) {
                coupon.setFaceValue(dto.getFaceValue());
            }
            if (CouponType.DISCOUNT == coupon.getType()) {
                coupon.setDiscount(dto.getDiscount());
            }
            coupon.setDrawLimit(CouponDrawLimit.valueOf(dto.getDrawLimit()));
            coupon.setLimitAmount(new BigDecimal(dto.getLimitAmount()));
            coupon.setLimitCount(dto.getLimitCount());
            coupon.setLeaveTotal(dto.getQuantity());
            coupon.setQuantity(dto.getQuantity());
            coupon.setSharing(Whether.valueOf(dto.getSharing()));
            coupon.setIsDelete(Whether.NO);
            coupon.setQuantityUsed(0l);
            coupon.setQuantityFrozen(0l);
            coupon.setStatus(MerchantCouponStatus.valueOf(dto.getStatus()));
            coupon.setShowOnCenter(Whether.valueOf(dto.getShowOnCenter()));
            coupon.setShowOnMerchant(Whether.valueOf(dto.getShowOnMerchant()));
            coupon.setUseScope(CouponUseScope.valueOf(dto.getUseScope()));
            coupon.setDateEnabled(dto.getDateEnabled());
            coupon.setDateDisabled(dto.getDateDisabled());
            coupon.setDateIssued(dto.getDateIssued());
            coupon.setIntroduction(dto.getIntroduction());
            coupon.setLogoUrl(dto.getLogoUrl());
            if (null!= dto.getIntegration()) {
                coupon.setIntegration(Whether.valueOf(dto.getIntegration()));
            }
            coupon = merchantCouponRepository.save(coupon);

            //IntegrationCouponAudit integrationCouponAudit = integrationCouponAuditRepository.findByCouponId(coupon.getId());

            if (null!= dto.getIntegration() && Whether.YES == Whether.valueOf(dto.getIntegration())) {
                //积分卡卷事件记录
                IntegrationEvent integrationEvent = new IntegrationEvent();
                integrationEvent.setEventType(IntegrationEventType.WAIT_AUDIT);
                integrationEvent.setMallId(userInfoDto.mall.getId());
                integrationEvent.setMerchantId(userInfoDto.merchant.getId());
                integrationEvent.setOperator(userInfoDto.merchant.getName());
                integrationEvent.setOperatorId(userInfoDto.merchant.getId());
                integrationEvent.setCouponId(coupon.getId());
                integrationEventRepository.save(integrationEvent);
                // 积分卡卷提交审核
                IntegrationCouponAudit integrationCouponAudit = new IntegrationCouponAudit();
                integrationCouponAudit.setMallId(userInfoDto.mall.getId());
                integrationCouponAudit.setMerchantId(userInfoDto.merchant.getId());
                integrationCouponAudit.setCouponId(coupon.getId());
                integrationCouponAudit.setStatus(IntegrationEventType.WAIT_AUDIT);
                integrationCouponAuditRepository.save(integrationCouponAudit);

                // TODO: 16/12/26 积分卡券使用情况 
            }

            List<Long> proList = RequestUtils.string2list(objectMapper, dto.getProductList());

            if (Whether.YES == Whether.valueOf(dto.getIsOnLine())) {

                if (CouponUseScope.PART_PRODUCT == CouponUseScope.valueOf(dto.getUseScope())) {
                    if (proList != null) {

                        Iterator<Long> itr = proList.iterator();
                        while (itr.hasNext()) {

                            Long productId = itr.next();
                            CouponMerchantProducts couponMerchantProducts = new CouponMerchantProducts();
                            couponMerchantProducts.setProductId(productId);
                            couponMerchantProducts.setCouponId(coupon.getId());
                            couponMerchantProducts.setIsDelete(Whether.NO);
                            couponMerchantProductsRepository.save(couponMerchantProducts);

                        }
                    } else {
                        log.warn("======================>**** proList is empty ******************无法获取产品数据");
                        return;
                    }

                }
            }

            if (CouponUseScope.PART_STORE == CouponUseScope.valueOf(dto.getUseScope())) {
                List<Long> storeList = RequestUtils.string2list(objectMapper, dto.getStoreList());
                for (Iterator<Long> itr = storeList.iterator(); itr.hasNext(); ) {
                    Long storeId = itr.next();
                    CouponMerchantStore couponMerchantStore = new CouponMerchantStore();
                    couponMerchantStore.setStoreId(storeId);
                    couponMerchantStore.setCouponId(coupon.getId());
                    couponMerchantStore.setIsDelete(Whether.NO);
                    couponMerchantStoreRepository.save(couponMerchantStore);
                }
            }

            //广播消息
            SysMessageHelper.SINGLETON.pushOpMsg(SysMessageConstants.M2M_MALL_MERCHANT_COUPON_SAVE_PENDING_AUDIT, null, coupon.getMallId(),null);

        };

        return doing.go(request, log);

    }

    /**
     * @api {post} /merchant/coupon/update B端 卡券 更新
     * @apiGroup merchant_coupon
     * @apiVersion 1.0.0
     * @apiHeader  {String} userToken 用户token
     * @apiHeader {String} domain    请求域名
     * @apiParam  {Long} id <code>必要参数</code> 卡券ID
     * @apiParam  {String} name                 名称
     * @apiParam  {Long} quantity                 发放总量
     * @apiParam  {String} sharing <code>必须为 YES (共享)| NO（不共享） </code>是否共享到卡券市场
     * @apiParam  {String} showOnMerchant <code>必须为 YES (共享)| NO（不共享） </code>是否发布到店铺首页
     * @apiParam  {String} showOnCenter <code>必须为 YES (共享)| NO（不共享） </code>是否发布到领券中心
     * @apiParam {String} integration: <code>必须为 YES("是"), NO("否")</code> 是否发布到积分渠道
     * @apiParam  {String} logoUrl                图片URL
     * @apiParam  {String} introduction           说明
     * @apiSuccessExample {json} Success-Response:
     *{
     *  "code": "1",
     *  "desc": "成功"
     *}
     */
    @Transactional
    @RequestMapping(value = Routes.MERCHANT_COUPON_UPDATE, method = RequestMethod.POST)
    public JsonResult updateCoupon(@RequestBody MerchantCouponDto dto, HttpServletRequest request) throws RuntimeException {

        UserInfoDto userInfoDto = userHelper.getSession(request);
        RestDoing doing = jsonResult -> {
            if (dto.getId() == null) {
                jsonResult.remind("卡券ID不能为空",log);
                return;
            }

            MerchantCoupon coupon = this.merchantCouponRepository.findByIdAndMerchantId(dto.getId(), userInfoDto.merchant.getId());
            if (coupon == null) {
                jsonResult.remind("加载卡券数据出错",log);
                return;
            }
            if (StringUtils.isBlank(dto.getSharing()) || !EnumUtils.isValidEnum(Whether.class, dto.getSharing())) {
                jsonResult.remind("sharing  不能为空 值必须为 YES(\"是\"), NO(\"否\")",log);
                return;
            }
            if (StringUtils.isBlank(dto.getShowOnMerchant()) || !EnumUtils.isValidEnum(Whether.class, dto.getShowOnMerchant())) {
                jsonResult.remind("showOnMerchant  不能为空 值必须为 YES(\"是\"), NO(\"否\")",log);
                return;
            }
            if (StringUtils.isBlank(dto.getShowOnCenter()) || !EnumUtils.isValidEnum(Whether.class, dto.getShowOnCenter())) {
                jsonResult.remind("showOnCenter  不能为空 值必须为 YES(\"是\"), NO(\"否\")",log);
                return;
            }
            if (dto.getQuantity() != null) {
                Long useTotal = coupon.getQuantity() - coupon.getLeaveTotal();
                if (dto.getQuantity() < useTotal) {
                    jsonResult.remind("发放数量不能小于已使用数量,已使用数量{" + useTotal + "}",log);
                    return;
                }
                if (dto.getQuantity() > coupon.getQuantity()) {
                    coupon.setLeaveTotal(coupon.getLeaveTotal() + (dto.getQuantity() - coupon.getQuantity()));
                }
                if (dto.getQuantity() < coupon.getQuantity()) {
                    coupon.setLeaveTotal(coupon.getLeaveTotal() - (coupon.getQuantity() - dto.getQuantity()));
                }
                coupon.setQuantity(dto.getQuantity());
            }
            if (StringUtils.isNotBlank(dto.getName())) {
                coupon.setName(dto.getName());
            }
            if (StringUtils.isNotBlank(dto.getSharing())) {
                coupon.setSharing(Whether.valueOf(dto.getSharing()));
            }
            if (StringUtils.isNotBlank(dto.getLogoUrl())) {
                coupon.setLogoUrl(dto.getLogoUrl());
            }
            if (StringUtils.isNotBlank(dto.getShowOnMerchant())) {
                coupon.setShowOnMerchant(Whether.valueOf(dto.getShowOnMerchant()));
            }
            if (StringUtils.isNotBlank(dto.getShowOnCenter())) {
                coupon.setShowOnCenter(Whether.valueOf(dto.getShowOnCenter()));
            }
            if (StringUtils.isNotBlank(dto.getIntroduction())) {
                coupon.setIntroduction(dto.getIntroduction());
            }
            if(dto.getLimitCount()!=null) {
                coupon.setLimitCount(dto.getLimitCount());
            }

            // TODO: 16/12/17 积分卡卷修改 审核
            if (null!= dto.getIntegration() && Whether.YES == Whether.valueOf(dto.getIntegration())) {
                //积分卡卷事件记录
                IntegrationEvent integrationEvent = new IntegrationEvent();
                integrationEvent.setEventType(IntegrationEventType.WAIT_AUDIT);
                integrationEvent.setMallId(userInfoDto.mall.getId());
                integrationEvent.setOperator(userInfoDto.merchant.getName());
                integrationEvent.setMerchantId(userInfoDto.merchant.getId());
                integrationEvent.setOperatorId(userInfoDto.merchant.getId());
                integrationEvent.setCouponId(coupon.getId());
                integrationEventRepository.save(integrationEvent);
                // todo 积分卡卷提交审核
                IntegrationCouponAudit integrationCouponAudit = integrationCouponAuditRepository.findByCouponIdAndMerchantIdAndIsDelete(coupon.getId(), coupon.getMerchantId(), Whether.NO);
                if (integrationCouponAudit == null) {
                    integrationCouponAudit = new IntegrationCouponAudit();
                }
                integrationCouponAudit.setMallId(userInfoDto.mall.getId());
                integrationCouponAudit.setMerchantId(userInfoDto.merchant.getId());
                integrationCouponAudit.setCouponId(coupon.getId());
                integrationCouponAudit.setStatus(IntegrationEventType.WAIT_AUDIT);
                integrationCouponAuditRepository.save(integrationCouponAudit);
                //状态待审核
                coupon.setStatus(MerchantCouponStatus.WAIT_AUDIT);
            }

            coupon = merchantCouponRepository.saveAndFlush(coupon);

            //广播消息
            SysMessageHelper.SINGLETON.pushOpMsg(SysMessageConstants.M2M_MALL_MERCHANT_COUPON_UPDATE_PENDING_AUDIT, null, coupon.getMallId(),null);


        };

        return doing.go(request, log);

    }


    /**
     * @api {get} /merchant/coupon/info B端 卡券信息
     * @apiGroup merchant_coupon
     * @apiVersion 1.0.0
     * @apiHeader  {String} userToken 用户token
     * @apiHeader {String} domain    请求域名
     * @apiParam  {String} id 卡券ID
     * @apiSuccessExample {json} Success-Response:
     * {
     *  "code": "1",
     *  "desc": "成功",
     *  "data":
     *      {
     *      "id": 63,
     *      "dateCreated": "2016-10-18 19:43:18",
     *      "lastUpdated": "2016-10-18 19:43:19",
     *      "version": 0,
     *      "type": "DISCOUNT",
     *      "name": "抵用券测试6",
     *      "discount": 8.8,
     *      "limitAmount": 0,
     *      "quantity": 200,
     *      "leaveTotal": 200,
     *      "dateEnabled": "2016-10-18 00:00:00",
     *      "dateDisabled": "2016-10-19 00:00:00",
     *      "useScope": "PART_PRODUCT",
     *      "dateIssued": "2016-10-18 19:43:04",
     *      "drawLimit": "DAYS",
     *      "limitCount": 5,
     *      "sharing": "NO",
     *      "showOnCenter": "NO",
     *      "showOnMerchant": "NO",
     *      "logoUrl": "http://pic.server.com/1112.png",
     *      "introduction": "just for test VOUCHERS",
     *      "status": "WAIT_ISSUE",
     *      "merchantId": 1,
     *      "mallId": 1
     *      }
     * }
     */
    @RequestMapping(value = Routes.MERCHANT_COUPON_INFO, method = RequestMethod.GET)
    public JsonResult couponInfo(MerchantCouponDto dto, HttpServletRequest request) {
        UserInfoDto userInfoDto = userHelper.getSession(request);
        RestDoing doing = jsonResult -> {
            if (dto.getId() == null) {
                jsonResult.remind("卡券ID 不能为空", log);
                return;
            }
            MerchantCoupon coupon = merchantCouponRepository.findOne(dto.getId());
            if (coupon == null) {
                jsonResult.remind("加载卡券信息失败", log);
                return;
            }
            MerchantCouponDto couponDto = new MerchantCouponDto();
            couponDto.setDrawLimit(coupon.getDrawLimit().toString());
            couponDto.setQuantityFrozen(coupon.getQuantityFrozen());
            couponDto.setQuantityUsed(coupon.getQuantityUsed());
            couponDto.setLimitAmount(coupon.getLimitAmount().doubleValue());
            couponDto.setType(coupon.getType().toString());
            couponDto.setName(coupon.getName());
            couponDto.setFaceValue(coupon.getFaceValue());
            couponDto.setDiscount(coupon.getDiscount());
            couponDto.setLimitCount(coupon.getLimitCount());
            couponDto.setLeaveTotal(coupon.getLeaveTotal());
            couponDto.setQuantity(coupon.getQuantity());
            couponDto.setSharing(coupon.getSharing().toString());
            couponDto.setStatus(coupon.getStatus().toString());
            couponDto.setShowOnCenter(coupon.getShowOnCenter().toString());
            couponDto.setShowOnMerchant(coupon.getShowOnMerchant().toString());
            couponDto.setUseScope(coupon.getUseScope().toString());
            couponDto.setDateEnabled(coupon.getDateEnabled());
            couponDto.setDateDisabled(coupon.getDateDisabled());
            couponDto.setDateIssued(coupon.getDateIssued());
            couponDto.setDateCreated(coupon.getDateCreated());
            couponDto.setLastUpdated(coupon.getLastUpdated());
            couponDto.setIntroduction(coupon.getIntroduction());
            couponDto.setLogoUrl(coupon.getLogoUrl());
            if (coupon.getUseScope() == CouponUseScope.PART_STORE) {
                List<CouponMerchantStore> storeList = this.couponMerchantStoreRepository.findByCouponIdAndIsDelete(coupon.getId(), Whether.NO);
                StringBuffer storeIds = new StringBuffer();
                for (int i = 0; i < storeList.size(); i++) {
                    CouponMerchantStore store = storeList.get(i);
                    if (i < storeList.size() - 1) {
                        storeIds.append(store.getStoreId() + ",");
                    } else {
                        storeIds.append(store.getStoreId());
                    }
                }
                couponDto.setStoreList(storeIds.toString());
                couponDto.setCouponStoreCount(new Long(storeList.size()));
            }
            if (coupon.getUseScope() == CouponUseScope.PART_PRODUCT) {
                List<CouponMerchantProducts> productsList = this.couponMerchantProductsRepository.findByCouponIdAndIsDelete(coupon.getId(), Whether.NO);
                StringBuffer productIds = new StringBuffer();
                for (int i = 0; i < productsList.size(); i++) {
                    CouponMerchantProducts product = productsList.get(i);
                    if (i < productsList.size() - 1) {
                        productIds.append(product.getProductId() + ",");
                    } else {
                        productIds.append(product.getProductId());
                    }
                }

                couponDto.setProductList(productIds.toString());
                couponDto.setCouponProductCount(new Long(productsList.size()));

            }
            jsonResult.data = couponDto;
        };
        return doing.go(request, log);
    }

    /**
     * @api {put} /merchant/coupon/status/update B端 卡券 上|下架
     * @apiGroup merchant_coupon
     * @apiVersion 1.0.0
     * @apiHeader  {String} userToken 用户token
     * @apiHeader {String} domain    请求域名
     * @apiParam  {List} ids 卡券ID集合
     * @apiParam  {String}  status   <code>必须为 WAIT_ISSUE("待发放"), ISSUED("已发放"), SOLDOUT("已下架"), EXPIRED("已过期"), DELETED("已删除")</code>  卡券状态
     * @apiSuccessExample {json} Success-Response:
     * {
     *  "code": "1",
     *  "desc": "成功"
     * }
     */
    @RequestMapping(value = Routes.MERCHANT_COUPON_STATUS_UPDATE, method = RequestMethod.PUT)
    public JsonResult updateCouponStatus(@RequestBody MerchantCouponDto dto, HttpServletRequest request) {

        UserInfoDto userInfoDto = userHelper.getSession(request);
        RestDoing doing = jsonResult -> {

            if (dto.getIds() == null || dto.getIds().isEmpty()) {
                jsonResult.remind("卡券ID集合 不能为空", log);
                return;
            }
            if (StringUtils.isBlank(dto.getStatus()) || !EnumUtils.isValidEnum(MerchantCouponStatus.class, dto.getStatus())) {
                jsonResult.remind("status 取值必须为 WAIT_ISSUE(\"待发放\"), ISSUED(\"已发放\"), SOLDOUT(\"已下架\"), EXPIRED(\"已过期\"), DELETED(\"已删除\")", log);
                return;
            }
            dto.getIds().forEach(id -> {
                MerchantCoupon coupon = merchantCouponRepository.findByIdAndMerchantId(id, userInfoDto.merchant.getId());
                if (coupon == null) {
                    jsonResult.remind("加载卡券数据失败", log);
                    return;
                }
                if (MerchantCouponStatus.SOLDOUT != MerchantCouponStatus.valueOf(dto.getStatus())) {
                    if (System.currentTimeMillis() >= coupon.getDateEnabled().getTime() && System.currentTimeMillis() <= coupon.getDateDisabled().getTime()) {
                        coupon.setStatus(MerchantCouponStatus.ISSUED);
                    } else if (System.currentTimeMillis() > coupon.getDateDisabled().getTime()) {
                        coupon.setStatus(MerchantCouponStatus.EXPIRED);
                    } else {
                        coupon.setStatus(MerchantCouponStatus.WAIT_ISSUE);
                    }
                }
                coupon.setStatus(MerchantCouponStatus.valueOf(dto.getStatus()));
                merchantCouponRepository.save(coupon);
            });
        };
        return doing.go(request, log);
    }

    /**
     * @api {put} /merchant/coupon/send/out B端  卡券发放
     * @apiGroup merchant_coupon
     * @apiVersion 1.0.0
     * @apiHeader  {String} userToken 用户token
     * @apiHeader {String} domain    请求域名
     * @apiParam  {Long} id 卡券ID
     * @apiSuccessExample {json} Success-Response:
     * {
     * "code": "1",
     * "desc": "成功",
     *  "data": {
     *      "id": 125,
     *      "promoteUrl": "http://uploads.rockcent.com/dev/coupon/promote/201611/8144041195ba45c141-1613-4bdc-ba46-4a3345a0f3e3giftPacketPromote.jpg",
     *      "sendOutUrl": "http://beta.c.dev.rockcent.com/mall.php?method=detail&couponId=125&salesCode=B@AfvahtT"
     *      }
     *  }
     */
    @RequestMapping(value = Routes.MERCHANT_COUPON_SEND_OUT, method = RequestMethod.PUT)
    public JsonResult sendOutCoupon(@RequestBody MerchantCouponDto dto, HttpServletRequest request) {

        UserInfoDto userInfoDto = userHelper.getSession(request);
        RestDoing doing = jsonResult -> {

            if (dto.getId() == null) {
                jsonResult.remind("卡券ID 不能为空", log);
                return;
            }
            Mall mall = mallRepository.findOne(userInfoDto.mall.getId());
            if (mall == null) {
                jsonResult.remind("平台不存在,请联系开发人员",log);
                return;
            }
            Merchant merchant = merchantRepository.findOne(userInfoDto.merchant.getId());
            String host = mall.getCustomerClientDomain();
            if (StringUtils.isBlank(host)) {
                host = mall.getMobileHostName();
            }
            MerchantCoupon coupon = merchantCouponRepository.findByIdAndMerchantId(dto.getId(), userInfoDto.merchant.getId());
            if (coupon == null) {
                jsonResult.remind("没有对应的卡券记录", log);
                return;
            }
            StringBuffer url = new StringBuffer();
            //推广链接，待定 http://beta.c.uat.rockcent.com/wechat_new/#/wechat/cardTake/19
            url.append("http://").append(host).append("/wechat/cardTake/").append(coupon.getId()).append("/?id=").append(coupon.getId());

            QrCodeDto qrCodeDto = new QrCodeDto();
            qrCodeDto.setId(userInfoDto.getId());
            qrCodeDto.setMallId(userInfoDto.mall.getId());
            qrCodeDto.setMerchantId(userInfoDto.merchant.getId());
            UploadImageFileDto uploadImageFileDto = qrCodeHelper.createQRCode(qrCodeDto, url.toString(), "channelSendOutQR.jpg", UploadFileBusinessType.MERCHANT_COUPON_PROMOTE, prop.env, prop.aliyunOssBucketName, prop.domainUploadsHttp);
            coupon.setPromoteUrl(uploadImageFileDto.getPath());

            MerchantCouponDto couponDto = new MerchantCouponDto();

            merchantCouponRepository.save(coupon);
            couponDto.setId(coupon.getId());
            couponDto.setSendOutUrl(url.toString());
            couponDto.setPromoteUrl(coupon.getPromoteUrl());
            jsonResult.data = couponDto;
        };
        return doing.go(request, log);
    }

     /**
     * @api {get}  /merchant/coupon/useage B端  查看卡券适用门店|产品信息
     * @apiGroup merchant_coupon
     * @apiVersion 1.0.0
     * @apiHeader  {String} userToken 用户token
     * @apiHeader {String} domain    请求域名
     * @apiParam  {Long} id 卡券ID
      * @apiParam {String} productList: <code>格式[1,2,3,4]</code> 适用产品ID集合
      * @apiParam {String} storeList: <code>格式[1,2,3,4]</code> 适用门店ID集合
     * @apiSuccessExample {json} Success-Response:
     * {
     * "code": "1",
     * "desc": "成功",
     *  "data": {
     *      "id": 125,
     *      "promoteUrl": "http://uploads.rockcent.com/dev/coupon/promote/201611/8144041195ba45c141-1613-4bdc-ba46-4a3345a0f3e3giftPacketPromote.jpg",
     *      "sendOutUrl": "http://beta.c.dev.rockcent.com/mall.php?method=detail&couponId=125&salesCode=B@AfvahtT"
     *      }
     *  }
     */
    @RequestMapping(value = Routes.MERCHANT_COUPON_USEAGE, method = RequestMethod.GET)
    public JsonResult showCouponUseAge(MerchantCouponDto dto, HttpServletRequest request) {
        UserInfoDto userInfoDto = userHelper.getSession(request);
        RestDoing doing = jsonResult -> {

            if (dto.getId() == null) {
                jsonResult.remind("卡券ID 不能为空", log);
                return;
            }
            MerchantCoupon coupon = this.merchantCouponRepository.findByIdAndMerchantId(dto.getId(), userInfoDto.merchant.getId());
            if (coupon.getUseScope() == CouponUseScope.PART_STORE) {
                List<Long> storeIdList = RequestUtils.string2list(objectMapper, dto.getStoreList());
                if (storeIdList == null || storeIdList.isEmpty()) {
                    jsonResult.remind("加载产品列表失败",log);
                    return;
                }
                List<MerchantStore> storeList = merchantStoreRepository.findByStatusAndExchangeAndIdInAndMerchantId(MerchantStoreStatus.ENABLE, Whether.YES, storeIdList, userInfoDto.merchant.getId());
                jsonResult.data = storeList;
            }
            if (coupon.getUseScope() == CouponUseScope.PART_PRODUCT) {
                List<Long> proList = RequestUtils.string2list(objectMapper, dto.getProductList());
                if (proList == null || proList.isEmpty()) {
                    jsonResult.remind("加载产品列表失败",log);
                    return;
                }
                List<Product> productList = merchantProductRepository.findByMerchantIdAndIdIn(userInfoDto.merchant.getId(), proList);
                jsonResult.data = productList;
            }

        };

        return doing.go(request, log);
    }


}
